﻿using MvCameraControl;
using System;
using System.Collections.Generic;

namespace Camera
{
    public class CameraHikvision : CameraBase
    {
        private const DeviceTLayerType devLayerType = DeviceTLayerType.MvGigEDevice | DeviceTLayerType.MvUsbDevice | DeviceTLayerType.MvGenTLCameraLinkDevice
            | DeviceTLayerType.MvGenTLCXPDevice | DeviceTLayerType.MvGenTLXoFDevice;
        private IDevice device;
        private bool isGrabbing;        // ch:是否正在取图 | en: Grabbing flag
        private string _serialNumber;

        public override event ReadImageDelegate ReadImageEvent;
        public override event ConnectLossDelegate ConnectLossEvent;

        public CameraHikvision()
        {

        }

        public static string[] DeviceListAcq()
        {
            // ch: 初始化 SDK | en: Initialize SDK
            SDKSystem.Initialize();

            try
            {
                List<IDeviceInfo> devInfoList;

                // ch:枚举设备 | en:Enum device
                int ret = DeviceEnumerator.EnumDevices(devLayerType, out devInfoList);
                if (ret != MvError.MV_OK)
                {
                    return null;
                }

                if (0 == devInfoList.Count)
                {
                    return null;
                }

                // ch:打印设备信息 en:Print device info
                int devIndex = 0;
                string[] deviceList = new string[devInfoList.Count];
                foreach (var devInfo in devInfoList)
                {
                    deviceList[devIndex] = devInfo.SerialNumber;
                    devIndex++;
                }
                return deviceList;
            }
            catch (Exception)
            {
                return null;
            }
        }

        public override bool Open(string _serialNumber)
        {
            this._serialNumber = _serialNumber;
            // ch: 初始化 SDK | en: Initialize SDK
            SDKSystem.Initialize();

            try
            {
                List<IDeviceInfo> devInfoList;

                // ch:枚举设备 | en:Enum device
                int ret = DeviceEnumerator.EnumDevices(devLayerType, out devInfoList);
                if (ret != MvError.MV_OK)
                {
                    return false;
                }

                if (0 == devInfoList.Count)
                {
                    return false;
                }

                // ch:打印设备信息 en:Print device info
                foreach (var devInfo in devInfoList)
                {
                    if (_serialNumber == devInfo.SerialNumber)
                    {
                        // ch:创建设备 | en:Create device
                        device = DeviceFactory.CreateDevice(devInfo);

                        ret = device.Open();
                        if (ret != MvError.MV_OK)
                        {
                            return false;
                        }

                        // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
                        if (device is IGigEDevice)
                        {
                            int packetSize;
                            ret = (device as IGigEDevice).GetOptimalPacketSize(out packetSize);
                            if (packetSize > 0)
                            {
                                device.Parameters.SetIntValue("GevSCPSPacketSize", packetSize);
                            }
                        }

                        // ch:设置采集连续模式 | en:Set Continues Aquisition Mode
                        device.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");

                        //ch: 设置合适的缓存节点数量 | en: Setting the appropriate number of image nodes
                        device.StreamGrabber.SetImageNodeNum(5);

                        // ch:注册回调函数 | en:Register image callback
                        device.StreamGrabber.FrameGrabedEvent += FrameGrabedEventHandler;

                        device.DeviceExceptionEvent += ExceptionEventHandler;
                        return true;
                    }
                }
            }
            catch (Exception)
            {

            }
            return false;
        }

        private void FrameGrabedEventHandler(object sender, FrameGrabbedEventArgs e)
        {
            if (e.FrameOut.Image.PixelDataPtr == IntPtr.Zero)
            {
                return;
            }
            ReadImageEvent(new Imgdata { data = e.FrameOut.Image.PixelDataPtr, width = (int)e.FrameOut.Image.Width, height = (int)e.FrameOut.Image.Height });
        }

        private void ExceptionEventHandler(object sender, DeviceExceptionArgs e)
        {
            if (e.MsgType == DeviceExceptionType.DisConnect)
            {
                ConnectLossEvent($"相机 {_serialNumber} 异常掉线，重新连接中。。。");
                while (true)
                {
                    if (device != null)
                    {
                        device.StreamGrabber.StopGrabbing();
                        device.Close();
                        device.Dispose();
                        device = null;
                    }
                    if (!Open(_serialNumber))
                    {
                        continue;
                    }
                }
            }
        }

        public override bool Close()
        {
            // ch:取流标志位清零 | en:Reset flow flag bit
            if (isGrabbing == true)
            {
                StopGrab();
            }
            // ch:关闭设备 | en:Close Device
            if (device != null)
            {
                device.Close();
                device.Dispose();
            }
            return true;
        }

        public override bool StartGrab()
        {
            // ch:标志位置位true | en:Set position bit true
            isGrabbing = true;
            // ch:开启抓图 || en: start grab image
            int ret = device.StreamGrabber.StartGrabbing();
            if (ret != MvError.MV_OK)
            {
                isGrabbing = false;
                return false;
            }
            return true;
        }

        public override void StopGrab()
        {
            // ch:标志位设为false | en:Set flag bit false
            isGrabbing = false;
            // ch:停止抓图 | en:Stop grabbing
            device.StreamGrabber.StopGrabbing();
        }

        public override void SetTriggerMode(TriggerMode triggerMode)
        {
            // ch:设置触发模式为off || en:set trigger mode as off
            device.Parameters.SetEnumValue("TriggerMode", (uint)triggerMode);
        }

        public override void SetTriggerSource(TriggerSource triggerSource)
        {
            // ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0;
            //           1 - Line1;
            //           2 - Line2;
            //           3 - Line3;
            //           4 - Counter;
            //           7 - Software;
            device.Parameters.SetEnumValueByString("TriggerSource", triggerSource.ToString());
        }

        public override bool TriggerSoftware()
        {
            // ch:触发命令 | en:Trigger command
            device.Parameters.SetCommandValue("TriggerSoftware");
            return true;
        }

        public override string GetSerialNumber()
        {
            return _serialNumber;
        }

        public override double GetParameter(string key)
        {
            IFloatValue floatValue;
            int result = device.Parameters.GetFloatValue(key, out floatValue);
            if (result == MvError.MV_OK)
            {
                return floatValue.CurValue;
            }
            return 0;
        }

        public override void SetParameter(string key, double fValue)
        {
            device.Parameters.SetFloatValue(key, (float)fValue);
        }

        public override void UserSave()
        {
            //m_pMyCamera.MV_CC_SetEnumValue_NET("TriggerSource", nValue);
            //m_pMyCamera.mv_cc
        }

        public override void LoadConfigurationFromFile(string fileName)
        {

        }
    }
}
